
NAMESPACE_BEGIN(interp)

template <class EncodingT>
shared_ptr< Base<EncodingT> > Program<EncodingT>::interpret(Context<EncodingT> & c) 
{
	m_declaration->interpret(c);
    return m_block->interpret(c);
}

template <class EncodingT>
bool Program<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    bool success = false;
	typename EncodingT::string_t instructions;
    shared_ptr< Term<EncodingT> > block;
	shared_ptr< Term<EncodingT> > declaration;
    success = Declaration<EncodingT>::parse(buf, declaration, instructions) && 
	          Block<EncodingT>::parse(instructions, block, true);
    // clean program analysis
    Instruction<EncodingT>::clean();
    Assignable<EncodingT>::clean();
    if (success)
    {
        value.reset(new Program<EncodingT>(declaration, block));
    }
    return success; 
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Declaration<EncodingT>::interpret(Context<EncodingT> & c)
{
    shared_ptr< Base<EncodingT> > ret(new Base<EncodingT>());
    for (iterator i = m_functions.begin(); i < m_functions.end(); ++i)
    {
        shared_ptr< Function<EncodingT> > function = dynamic_pointer_cast< Function<EncodingT> >(*i);
        if (function)
        {
			c.declare(function->getName(), function);
		}
    }
    return ret;
}

template <class EncodingT>
bool Declaration<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value, typename EncodingT::string_t & instructions)
{
	vector< shared_ptr< Term<EncodingT> > > declarationList;
    shared_ptr< Term<EncodingT> > declaration;
    typename EncodingT::string_t sequence;
    Category * logger = &Category::getInstance(LOGNAME);
    typename EncodingT::string_t::const_iterator i = buf.begin();
    typename EncodingT::string_t::const_iterator j = buf.begin();
    typename EncodingT::string_t::const_iterator end = buf.end();
    
    bool success = true;
	bool parsing = true;
    while (i!=end && success && parsing)
    {
        // advance to first no space character
        i = next_word<EncodingT>(i, end);

        if (i != end)
        {
			if ((j = CommentBlock<EncodingT>::look_for(i, buf.end())) != i)
            {
                sequence.assign(i, j);
                declaration.reset();
                success = CommentBlock<EncodingT>::parse(sequence, declaration);
                if (success)
                {
                    // add instruction
                    declarationList.push_back(declaration);
                    // advance index
                    i = j;
                }
            }
            // function block
            else if ((j = Function<EncodingT>::look_for(i, buf.end())) != i)
            {
                sequence.assign(i, j);
                declaration.reset();
                success = Function<EncodingT>::parse(sequence, declaration);
                if (success)
                {
                    // add function
                    declarationList.push_back(declaration);
                    // advance index
                    i = j;
                }
            }
            else
            {
                parsing = false;
            }
        }
    }
	if (success)
	{
		value.reset(new Declaration<EncodingT>(declarationList));
		instructions.assign(i, end);
	}
	else
	{
		typename EncodingT::string_t stopped(i, buf.end());
        logger->errorStream() << "instruction is invalid : " << A(stopped);
	}
    return success; 
}

template <class EncodingT>
typename EncodingT::string_t const& Function<EncodingT>::getName() const
{
	return m_name;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Function<EncodingT>::interpret(Context<EncodingT> & c)
{
    return m_block->interpret(c);
}

template <class EncodingT>
bool Function<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t expr = eat_space<EncodingT>(buf);
    typename EncodingT::string_t name, block;
    shared_ptr< Term<EncodingT> > block_value;
    bool success =  prefix<EncodingT>(expr, C("function"), expr, true) &&
                    suffix<EncodingT>(expr, C("endfunction"), expr, true) &&
					hyphenation<EncodingT>(expr, C("is"), name, block, true) &&
					is_identifier<EncodingT>(name) &&
                    Block<EncodingT>::parse(block, block_value);
    if (success)
    {
        value.reset(new Function<EncodingT>(name, block_value));
    }
    return success;  
}

template <class EncodingT>
typename Function<EncodingT>::char_iterator 
Function<EncodingT>::look_for(typename Function<EncodingT>::char_iterator start, typename Function<EncodingT>::char_iterator end)
{
    typename EncodingT::string_t::const_iterator i = start, j;
    if ( end-start > 20 &&
		 equal_symbol<EncodingT>(start, start+8, C("function")) &&
        (j = find_symbol<EncodingT>(start+8, end, C("endfunction")))!=end)
    {
        i = j + 11;
    }
    return i;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Block<EncodingT>::interpret(Context<EncodingT> & c)
{
    shared_ptr< Base<EncodingT> > ret(new Base<EncodingT>());
    for (iterator i = m_instructions.begin(); i < m_instructions.end(); ++i)
    {
        ret = (*i)->interpret(c);
    }
    return ret;
}

template <class EncodingT>
bool Block<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value, bool print)
{
    vector< shared_ptr< Term<EncodingT> > > blockList;
    shared_ptr< Term<EncodingT> > block;
    typename EncodingT::string_t sequence;
    Category * logger = &Category::getInstance(LOGNAME);
    typename EncodingT::string_t::const_iterator i = buf.begin();
    typename EncodingT::string_t::const_iterator j = buf.begin();
    typename EncodingT::string_t::const_iterator end = buf.end();
    
    bool success = true;
    while (i!=end && success)
    {
        // advance to first no space character
        i = next_word<EncodingT>(i, end);

        if (i != end)
        {
            // conditional block
            if ((j = ConditionalBlock<EncodingT>::look_for(i, buf.end())) != i)
            {
                sequence.assign(i, j);
                block.reset();
                success = ConditionalBlock<EncodingT>::parse(sequence, block);
                if (success)
                {
                    // add instruction
                    blockList.push_back(block);
                    // advance index
                    i = j;
                }
            }
            // repetitive block
            else if ((j = RepetitiveBlock<EncodingT>::look_for(i, buf.end())) != i)
            {
                sequence.assign(i, j);
                block.reset();
                success = RepetitiveBlock<EncodingT>::parse(sequence, block);
                if (success)
                {
                    // add instruction
                    blockList.push_back(block);
                    // advance index
                    i = j;
                }
            }
            // comment block
            else if ((j = CommentBlock<EncodingT>::look_for(i, buf.end())) != i)
            {
                sequence.assign(i, j);
                block.reset();
                success = CommentBlock<EncodingT>::parse(sequence, block);
                if (success)
                {
                    // add instruction
                    blockList.push_back(block);
                    // advance index
                    i = j;
                }
            }
            // instructions list
            else if ((j = InstructionsList<EncodingT>::look_for(i, buf.end())) != i)
            {
                sequence.assign(i, j);
                block.reset();
                success = InstructionsList<EncodingT>::parse(sequence, block);
                if (success)
                {
                    // add instruction
                    blockList.push_back(block);
                    // advance index
                    i = j;
                }
            }
            else
            {
                success = false;
            }
        }
    }
    if (success)
    {
        value.reset(new Block<EncodingT>(blockList));
    }
    else if (print)
    {
        typename EncodingT::string_t stopped(i, buf.end());
        logger->errorStream() << "instruction is invalid : " << A(stopped);
    }
    return success;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > InstructionsList<EncodingT>::interpret(Context<EncodingT> & c)
{
    return m_instruction->interpret(c);
}

template <class EncodingT>
bool InstructionsList<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    shared_ptr< Term<EncodingT> > instruction;
    typename EncodingT::string_t expr;
    bool success =  suffix<EncodingT>(buf, C(";"), expr) &&
                    Instruction<EncodingT>::parse(expr, instruction);
    if (success)
    {
        value.reset(new InstructionsList<EncodingT>(instruction));
    }
    return success;
}

template <class EncodingT>
typename InstructionsList<EncodingT>::char_iterator 
InstructionsList<EncodingT>::look_for(typename InstructionsList<EncodingT>::char_iterator start, typename InstructionsList<EncodingT>::char_iterator end)
{
    typename EncodingT::string_t::const_iterator i = start, j;
    if ( (j = find_symbol<EncodingT>(start, end, C(";"))) != end )
    {
        i = j + 1;
    }
    return i;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > CommentBlock<EncodingT>::interpret(Context<EncodingT> & c)
{
    return shared_ptr< Base<EncodingT> >(new Base<EncodingT>());
}

template <class EncodingT>
bool CommentBlock<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    shared_ptr< Term<EncodingT> > instruction;
    typename EncodingT::string_t expr;
    bool success =  embrace<EncodingT>(buf, C("/*"), C("*/"), expr);
    if (success)
    {
        value.reset(new CommentBlock<EncodingT>(expr));
    }
    return success;
}

template <class EncodingT>
typename CommentBlock<EncodingT>::char_iterator 
CommentBlock<EncodingT>::look_for(typename CommentBlock<EncodingT>::char_iterator start, typename CommentBlock<EncodingT>::char_iterator end)
{
    typename EncodingT::string_t::const_iterator i = start, j;
    if ( end-start > 2 &&
         equal_symbol<EncodingT>(start, start+2, C("/*")) &&
        (j = find_symbol<EncodingT>(start+2, end, C("*/")))!=end)
    {
        i = j + 2;
    }
    return i;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > RepetitiveBlock<EncodingT>::interpret(Context<EncodingT> & c)
{
    shared_ptr< Bool<EncodingT> > res(new Bool<EncodingT>());
    bool bool_value = false;
    do
    {
        shared_ptr< Base<EncodingT> > baseexpr = m_condition->interpret(c);
        shared_ptr< Bool<EncodingT> > boolexpr = dynamic_pointer_cast< Bool<EncodingT> >(baseexpr);
        if (boolexpr)
        {
            bool_value = boolexpr->getValue();
            if (bool_value)
            {
                m_instructions->interpret(c);
            }
        }
        else
        {
            Category * logger = &Category::getInstance(LOGNAME);
            logger->errorStream() << "invalid object, required : " << A(res->getClassName())
                                  << ", got " << A(baseexpr->getClassName());
        }
    } while (bool_value);
    return res;
}

template <class EncodingT>
bool RepetitiveBlock<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t expr = eat_space<EncodingT>(buf);
    typename EncodingT::string_t condition, instructions;
    shared_ptr< Term<EncodingT> > condition_value;
    shared_ptr< Term<EncodingT> > instructions_value;
    bool success =  prefix<EncodingT>(expr, C("while"), expr, true) &&
                    suffix<EncodingT>(expr, C("endwhile"), expr, true) &&
                    hyphenation<EncodingT>(expr, C("do"), condition, instructions, true) &&
                    /*Bool*/Instruction<EncodingT>::parse(condition, condition_value) &&
                    Block<EncodingT>::parse(instructions, instructions_value);
    if (success)
    {
        value.reset(new RepetitiveBlock<EncodingT>(condition_value, instructions_value));
    }
    return success;  
}

template <class EncodingT>
typename RepetitiveBlock<EncodingT>::char_iterator 
RepetitiveBlock<EncodingT>::look_for(typename RepetitiveBlock<EncodingT>::char_iterator start, typename RepetitiveBlock<EncodingT>::char_iterator end)
{
    typename EncodingT::string_t::const_iterator i = start, j = start, k = start;    
    k = next_space<EncodingT>(j, end);
    if (equal_symbol<EncodingT>(j, k, C("while")))
    {
        size_t cpt = 1;
        while (cpt != 0 && j != end)
        {
            j = next_word<EncodingT>(k, end);
            k = next_space<EncodingT>(j, end);
            if (equal_symbol<EncodingT>(j, k, C("while")))
            {
                ++cpt;
            }
            if (equal_symbol<EncodingT>(j, k, C("endwhile")))
            {
                --cpt;
            }
        }
        // found
        if (cpt == 0)
        {
            i = k;
        }
    }
    return i;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > ConditionalBlock<EncodingT>::interpret(Context<EncodingT> & c)
{
    shared_ptr< Bool<EncodingT> > res(new Bool<EncodingT>());
    shared_ptr< Base<EncodingT> > baseexpr = m_condition->interpret(c);
    shared_ptr< Bool<EncodingT> > boolexpr = dynamic_pointer_cast< Bool<EncodingT> >(baseexpr);
    if (boolexpr)
    {
        res = boolexpr;
        if (boolexpr->getValue())
        {
            m_if_instructions->interpret(c);
        }
        else if (m_else_instructions)
        {
            m_else_instructions->interpret(c);
        }
    }
    else
    {
        Category * logger = &Category::getInstance(LOGNAME);
        logger->errorStream() << "invalid object, required : " << A(res->getClassName())
                              << ", got " << A(baseexpr->getClassName());
    }
    return res;
}

template <class EncodingT>
bool ConditionalBlock<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t expr = eat_space<EncodingT>(buf);
    typename EncodingT::string_t condition, instructions, if_instructions, else_instructions;
    shared_ptr< Term<EncodingT> > condition_value;
    shared_ptr< Term<EncodingT> > if_instructions_value, else_instructions_value;
    bool success =  prefix<EncodingT>(expr, C("if"), expr, true) &&
                    suffix<EncodingT>(expr, C("endif"), expr, true) &&
                    hyphenation<EncodingT>(expr, C("then"), condition, instructions, true) &&
                    /*Bool*/Instruction<EncodingT>::parse(condition, condition_value) &&
                    ((hyphenation<EncodingT>(instructions, C("else"), if_instructions, else_instructions, true) &&
                      Block<EncodingT>::parse(if_instructions, if_instructions_value) &&
                      Block<EncodingT>::parse(else_instructions, else_instructions_value)) ||
                     Block<EncodingT>::parse(instructions, if_instructions_value));
    if (success)
    {
        value.reset(new ConditionalBlock<EncodingT>(condition_value, if_instructions_value, else_instructions_value));
    }
    return success;  
}

template <class EncodingT>
typename ConditionalBlock<EncodingT>::char_iterator 
ConditionalBlock<EncodingT>::look_for(typename ConditionalBlock<EncodingT>::char_iterator start, typename ConditionalBlock<EncodingT>::char_iterator end)
{
    typename EncodingT::string_t::const_iterator i = start, j = start, k = start;    
    k = next_space<EncodingT>(j, end);
    if (equal_symbol<EncodingT>(j, k, C("if")))
    {
        size_t cpt = 1;
        while (cpt != 0 && j != end)
        {
            j = next_word<EncodingT>(k, end);
            k = next_space<EncodingT>(j, end);
            if (equal_symbol<EncodingT>(j, k, C("if")))
            {
                ++cpt;
            }
            if (equal_symbol<EncodingT>(j, k, C("endif")))
            {
                --cpt;
            }
        }
        // found
        if (cpt == 0)
        {
            i = k;
        }
    }
    return i;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > FunctionCall<EncodingT>::interpret(Context<EncodingT> & c)
{
	shared_ptr< Base<EncodingT> > val(new Base<EncodingT>());
	shared_ptr< Term<EncodingT> > fct = c.getFunction(m_name);
	if (fct)
	{
		val = fct->interpret(c);
	}
    return val;
}

template <class EncodingT>
bool FunctionCall<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
	typename EncodingT::string_t expr;
    bool success = suffix<EncodingT>(buf, C(")"), expr) &&
				   suffix<EncodingT>(expr, C("("), expr) &&
				   is_identifier<EncodingT>(expr);
    if (success)
    {
        value.reset(new FunctionCall<EncodingT>(expr));
    } 
    return success; 
}

template <class EncodingT>
void Variable<EncodingT>::allocate(shared_ptr< Base<EncodingT> > const& value, Context<EncodingT> & c)
{
    if (dynamic_pointer_cast< Null<EncodingT> >(value))
    {
        c.remove(m_name);
    }
    else
    {
        c.add(m_name, value);
    }
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Variable<EncodingT>::interpret(Context<EncodingT> & c)
{
    return c.getObject(m_name);
}

template <class EncodingT>
bool Variable<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t identifier = eat_space<EncodingT>(buf);
    bool success = is_identifier<EncodingT>(identifier);
    if (success)
    {
        value.reset(new Variable<EncodingT>(identifier));
    } 
    return success; 
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Assignment<EncodingT>::interpret(Context<EncodingT> & c)
{
    shared_ptr< Base<EncodingT> > val = m_instruction->interpret(c);
    m_object->allocate(val, c);
    return val;
}

template <class EncodingT>
bool Assignment<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t left, right;
    shared_ptr< Term<EncodingT> > right_value;
    shared_ptr< Address<EncodingT> > left_value;
    bool success = binary_op<EncodingT>(buf, C("="), left, right) && 
                   Assignable<EncodingT>::parse(left, left_value) && 
                   Instruction<EncodingT>::parse(right, right_value);
    if (success)
    {
        value.reset(new Assignment<EncodingT>(left_value, right_value));
    }
    return success;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Copy<EncodingT>::interpret(Context<EncodingT> & c)
{
    shared_ptr< Base<EncodingT> > val = m_instruction->interpret(c)->clone();
    m_object->allocate(val, c);
    return val;
}

template <class EncodingT>
bool Copy<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t left, right;
    shared_ptr< Term<EncodingT> > right_value;
    shared_ptr< Address<EncodingT> > left_value;
    bool success = binary_op<EncodingT>(buf, C(":="), left, right) && 
                   Assignable<EncodingT>::parse(left, left_value) && 
                   Instruction<EncodingT>::parse(right, right_value);
    if (success)
    {
        value.reset(new Copy<EncodingT>(left_value, right_value));
    }
    return success;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Bracket<EncodingT>::interpret(Context<EncodingT> & c)
{
    return m_instruction->interpret(c);
}

template <class EncodingT>
bool Bracket<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t expr;
    shared_ptr< Term<EncodingT> > expr_value;
    bool success = embrace<EncodingT>(buf, C("("), C(")"), expr) && 
                   Instruction<EncodingT>::parse(expr, expr_value);
    if (success)
    {
        value.reset(new Bracket<EncodingT>(expr_value));
    }
    return success;
}

template <class EncodingT>
typename Bracket<EncodingT>::char_iterator 
Bracket<EncodingT>::look_for(typename Bracket<EncodingT>::char_iterator start, typename Bracket<EncodingT>::char_iterator end)
{
    typename EncodingT::string_t::const_iterator i = start;    
    if (start!=end && equal_symbol<EncodingT>(start, start+1, C("(")))
    {
        typename EncodingT::string_t::const_iterator j = start+1; 
        size_t cpt = 1;
        while (cpt != 0 && j != end)
        {
            if (equal_symbol<EncodingT>(j, j+1, C("(")))
            {
                ++cpt;
            }
            if (equal_symbol<EncodingT>(j, j+1, C(")")))
            {
                --cpt;
            }
            j++;
        }
        // found
        if (cpt == 0)
        {
            i = j;
        }
    }
    return i;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > MemberAccessOperator<EncodingT>::interpret(Context<EncodingT> & c)
{
    shared_ptr< Base<EncodingT> > obj = m_instruction->interpret(c);
    vector< shared_ptr< Base<EncodingT> > > parameters;
    for (size_t i = 0; i<m_params.size(); ++i)
    {
        parameters.push_back(m_params[i]->interpret(c));
    }
    return obj->invoke( m_methodName, parameters );
}

template <class EncodingT>
void MemberAccessOperator<EncodingT>::allocate(shared_ptr< Base<EncodingT> > const& value, Context<EncodingT> & c)
{
    shared_ptr< Base<EncodingT> > obj = m_instruction->interpret(c);
    vector< shared_ptr< Base<EncodingT> > > parameters;
    for (size_t i = 0; i<m_params.size(); ++i)
    {
        parameters.push_back(m_params[i]->interpret(c));
    }
    if (dynamic_pointer_cast< Null<EncodingT> >(value))
    {
        obj->invoke(C("remove") + m_methodName, parameters);
    }
    else
    {
        parameters.push_back(value);
        obj->invoke( m_methodName, parameters );
    }   
}

template <class EncodingT>
bool MemberAccessOperator<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
    typename EncodingT::string_t left, right, method;
    shared_ptr< Term<EncodingT> > left_value;
    vector< shared_ptr< Term<EncodingT> > > params_values;
    bool success = false;
    size_t i = buf.length();
    while ( i != EncodingT::string_t::npos && !success)
    {
        if (rbinary_op<EncodingT>(buf, C("."), left, right, i) && 
            Instruction<EncodingT>::parse(left, left_value))
        {
            typename EncodingT::string_t::const_iterator i = find_symbol<EncodingT>(right.begin(), right.end(), C("("));
            typename EncodingT::string_t parameters(i, right.end());
            method = eat_space<EncodingT>(typename EncodingT::string_t(right.begin(), i));

            success = is_identifier<EncodingT>(method);
            embrace<EncodingT>(parameters, C("("), C(")"), parameters);
             
            if (!parameters.empty())
            {
                vector<typename EncodingT::string_t> params;
                size_t j = 0;
                tuple_op<EncodingT>(parameters, C(","), params);
                params_values.clear();
                while (success && j<params.size())
                {
                    shared_ptr< Term<EncodingT> > expr_value;
                    success = Instruction<EncodingT>::parse(params[j], expr_value);
                    params_values.push_back(expr_value);
                    ++j;
                }
            }
        }
    }
    if (success)
    {
        value.reset(new MemberAccessOperator<EncodingT>(left_value, method, params_values));
    } 
    return success;
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Instruction<EncodingT>::interpret(Context<EncodingT> & c)
{
    return m_instruction->interpret(c);
}

template <class EncodingT>
bool Instruction<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Term<EncodingT> > & value)
{
   shared_ptr< Term<EncodingT> > instruction;
   bool success = false;
   IntructionsMap::const_iterator i = analyzed.find(buf);
   if (i == analyzed.end())
   {
       success =
           IncludeInstruction<EncodingT>::parse(buf, instruction)       || 
           PrintInstruction<EncodingT>::parse(buf, instruction)         ||
		   Copy<EncodingT>::parse(buf, instruction)               		||
           Assignment<EncodingT>::parse(buf, instruction)               ||
           OrOperator<EncodingT>::parse(buf, instruction)               ||
           AndOperator<EncodingT>::parse(buf, instruction)              ||
           NotEqualOperator<EncodingT>::parse(buf, instruction)         ||
           EqualOperator<EncodingT>::parse(buf, instruction)            ||
           InferiorOrEqualOperator<EncodingT>::parse(buf, instruction)  ||
           SuperiorOrEqualOperator<EncodingT>::parse(buf, instruction)  ||
           InferiorOperator<EncodingT>::parse(buf, instruction)         ||
           SuperiorOperator<EncodingT>::parse(buf, instruction)         ||
           PlusOperator<EncodingT>::parse(buf, instruction)             ||
           MinusOperator<EncodingT>::parse(buf, instruction)            || 
           MultiplyOperator<EncodingT>::parse(buf, instruction)         ||
           DivideOperator<EncodingT>::parse(buf, instruction)           ||
           ConcatOperator<EncodingT>::parse(buf, instruction)           ||
           UnaryMinusOperator<EncodingT>::parse(buf, instruction)       ||
           NotOperator<EncodingT>::parse(buf, instruction)              ||
           SizeOperator<EncodingT>::parse(buf, instruction)             ||
           MemberAccessOperator<EncodingT>::parse(buf, instruction)     ||
           ArrayOperator<EncodingT>::parse(buf, instruction)            || 
           Bracket<EncodingT>::parse(buf, instruction)                  ||
           BoolConstant<EncodingT>::parse(buf, instruction)             ||
           NumericConstant<EncodingT>::parse(buf, instruction)          ||
           StringConstant<EncodingT>::parse(buf, instruction)           ||
           NewOperator<EncodingT>::parse(buf, instruction)              ||
           DeleteOperator<EncodingT>::parse(buf, instruction)           ||
		   FunctionCall<EncodingT>::parse(buf, instruction)             ||
           Variable<EncodingT>::parse(buf, instruction);
       // memo
       analyzed.insert(std::make_pair(buf, std::make_pair(success, instruction)));
   }
   else
   {
       success = i->second.first;
       instruction = i->second.second;
   }
   if (success)
   {
       value.reset(new Instruction<EncodingT>(instruction));
   }
   return success;
}

template <class EncodingT>
void Instruction<EncodingT>::clean()
{
    analyzed.clear();
}

template <class EncodingT>
void Assignable<EncodingT>::allocate(shared_ptr< Base<EncodingT> > const& value, Context<EncodingT> & c)
{
    m_object->allocate(value, c);
}

template <class EncodingT>
shared_ptr< Base<EncodingT> > Assignable<EncodingT>::interpret(Context<EncodingT> & c)
{
    return m_object->interpret(c);
}

template <class EncodingT>
bool Assignable<EncodingT>::parse(typename EncodingT::string_t const& buf, shared_ptr< Address<EncodingT> > & value)
{
   shared_ptr< Term<EncodingT> > instruction;
   bool success = false;
   AssignablesMap::const_iterator i = analyzed.find(buf);
   if (i == analyzed.end())
   {
       success = 
            Variable<EncodingT>::parse(buf, instruction)             ||
            MemberAccessOperator<EncodingT>::parse(buf, instruction) ||
            ArrayOperator<EncodingT>::parse(buf, instruction);
       // memo
       analyzed.insert(std::make_pair(buf, std::make_pair(success, instruction)));
   }
   else
   {
       success = i->second.first;
       instruction = i->second.second;
   }
    if (success)
    {
        shared_ptr< Address<EncodingT> > object = dynamic_pointer_cast< Address<EncodingT> >(instruction);
        if (object)
        {
            value.reset(new Assignable<EncodingT>(object));
        }
        else
        {
            success = false;
        }
    }
    return success;
}

template <class EncodingT>
void Assignable<EncodingT>::clean()
{
    analyzed.clear();
}

NAMESPACE_END

